package com.vca.service.service.Impl;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageInfo;
import com.vca.common.constants.Constants;
import com.vca.common.constants.OrderRedisConstans;
import com.vca.common.exception.VcaException;
import com.vca.common.model.order.StoreOrderInfo;
import com.vca.common.model.sms.SmsTemplate;
import com.vca.common.model.system.SystemNotification;
import com.vca.common.model.user.User;
import com.vca.common.model.user.UserCard;
import com.vca.common.model.user.UserToken;
import com.vca.common.model.user.VcaUserCardRecord;
import com.vca.common.model.vca_product.VcaProduct;
import com.vca.common.request.CardPageRequest;
import com.vca.common.request.RemarkCardsRequest;
import com.vca.common.response.CardPageResponse;
import com.vca.common.response.CardProductResponse;
import com.vca.common.utils.PageUtils;
import com.vca.common.utils.VcaUtil;
import com.vca.common.vo.dateLimitUtilVo;
import com.vca.service.dao.user.UserCardDao;
import com.vca.service.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 礼品卡用户关系表 服务实现类
 * </p>
 *
 * @author chenBing
 * @since 2022-11-10
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class UserCardServiceImpl extends ServiceImpl<UserCardDao, UserCard> implements UserCardService {

    @Autowired
    private SystemConfigService systemConfigService;

    @Autowired
    private UserTokenService userTokenService;

    @Autowired
    private TemplateMessageService templateMessageService;

    @Autowired
    private SystemNotificationService systemNotificationService;

    @Autowired
    private SmsService smsService;

    @Autowired
    private SmsTemplateService smsTemplateService;

    @Autowired
    private UserService userService;

    @Autowired
    private VcaUserCardRecordService userCardRecordService;

    @Autowired
    private UserCardDao dao;

    @Autowired
    private VcaProductService productService;

    /**
     * @Description:礼品卡过期提前通知
     * @author:chenbing
     * @date 2022/12/30 14:16
     */
    @Override
    public void giftCardBeOverdue() {
        String dayCount = systemConfigService.getValueByKey(Constants.GIFT_CARD_DISABLE_TIME);
        // TODO: 2022/12/30 查询所有过期礼品卡
        LambdaQueryWrapper<UserCard> lqw = new LambdaQueryWrapper<>();
        lqw.le(UserCard::getEndTime, DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, Integer.parseInt(dayCount)));
        lqw.eq(UserCard::getIsDeleted, false);
        lqw.eq(UserCard::getStutus, 0);
        lqw.eq(UserCard::getNoticeStatus, 0);
        List<UserCard> userCardList = list(lqw);
        SystemNotification paySuccessOfEvent = systemNotificationService.getByMark(OrderRedisConstans.GIFT_CARD_EXPIRATION_REMINDER);
        if (paySuccessOfEvent.getIsRoutine().equals(1)) {
            userCardList.forEach(giftCard -> {
                // TODO: 2022/12/30 生成小程序订阅消息
                generateGiftCardBeOverdueRoutine(giftCard, paySuccessOfEvent.getRoutineId());
                giftCard.setNoticeStatus(1);
            });
        }
        if (paySuccessOfEvent.getIsWechat().equals(1)) {
            // TODO: 2023/1/3 公众号模板消息
            userCardList.forEach(giftCard -> {
                // TODO: 2022/12/30 生成小程序订阅消息
                generateGiftCardBeOverduePublic(giftCard, paySuccessOfEvent.getWechatId());
                giftCard.setNoticeStatus(1);
            });
        }
        if (paySuccessOfEvent.getIsSms().equals(1)) {
            // TODO: 2023/1/3 发送短信
            SmsTemplate smsTemplate = smsTemplateService.getDetail(paySuccessOfEvent.getSmsId());
            userCardList.forEach(giftCard -> {
                if (ObjectUtil.isNotNull(giftCard.getUid())) {
                    User user = userService.getById(giftCard.getUid());
                    if (ObjectUtil.isNotNull(user)) {
                        if (ObjectUtil.isNotNull(user.getPhone())) {
                            smsService.sendGiftCard(giftCard.getCardNo(), user.getPhone(), smsTemplate.getTempId(), "pages/user-gift-certificates-detail/index?id=" + giftCard.getId());
                        }
                    }
                    giftCard.setNoticeStatus(1);
                }
            });
        }
        updateBatchById(userCardList);
    }

    private void generateGiftCardBeOverduePublic(UserCard giftCard, Integer wechatId) {
        HashMap<String, Object> messageMap = new HashMap<>();
        messageMap.put("first", "您的礼品卡即将过期");
        messageMap.put("keyword1", userService.getById(giftCard.getUid()).getNickname());
        messageMap.put("keyword2", DateUtil.format(giftCard.getEndTime(), Constants.DATE_FORMAT));
        messageMap.put("remark", "您的卡还有" + systemConfigService.getValueByKey(Constants.GIFT_CARD_DISABLE_TIME) + "日即将到期，请尽快使用！");
        UserToken userToken = userTokenService.getTokenByUserIdException(giftCard.getUid(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        if (userToken != null) {
            templateMessageService.pushTemplatePublicMessage("pages/user-gift-certificates-detail/index?id=" + giftCard.getId(), wechatId, messageMap, userToken.getToken());
        }
    }

    /**
     * @Description:礼品卡过期改变状态
     * @author:chenbing
     * @date 2023/1/28 10:41
     */
    @Override
    public void giftCardOverdued() {
        UpdateWrapper<UserCard> updateWrapper = new UpdateWrapper<UserCard>().le("end_time", new Date()).eq("stutus", 0).set("stutus", 2);
        update(updateWrapper);
    }

    /**
     * @description 礼品卡管理分页
     * @param request
     * @author Li
     * @date 2023/8/29 15:14
     * @return {@link PageInfo}<{@link CardPageResponse}>
     */
    @Override
    public PageInfo<CardPageResponse> pageCard(CardPageRequest request) {
        List<CardPageResponse> responses = this.cardPage(request);
        responses.forEach(r->{
            if (ObjectUtil.isNotEmpty(r.getPhone())){
                r.setPhone(r.getPhone().replaceAll("(\\d{3})\\d{4}(\\d{4})","$1****$2"));
            }
        });
        return PageUtils.startPage(responses,request.getPage(),request.getLimit());
    }

    /**
     * @description 礼品卡管理分页
     * @param request
     * @author Li
     * @date 2023/8/29 15:14
     * @return {@link PageInfo}<{@link CardPageResponse}>
     */
    @Override
    public List<CardPageResponse> cardPage(CardPageRequest request){
        if (ObjectUtil.isNotEmpty(request.getDateLimit())){
            dateLimitUtilVo dateLimit = com.vca.common.utils.DateUtil.getDateLimit(request.getDateLimit());
            request.setStartTime(dateLimit.getStartTime());
            request.setEndTime(dateLimit.getEndTime());
        }
        List<CardPageResponse> responses = dao.pageCard(request);
        responses.forEach(r->{
            r.setGiftStatus(ObjectUtil.isNotEmpty(r.getGiftTime()));
        });
        if (ObjectUtil.isEmpty(responses)){
            return responses;
        }
        Map<String,String> map=new HashMap<>();
        responses.forEach(r->{
            if (ObjectUtil.isNotEmpty(map.get(r.getId().toString()))) {
                if (r.getRefundStatus().equals(0)) {
                    map.put(r.getId().toString(), r.getOrderId());
                }
            }else {
                map.put(r.getId().toString(), r.getOrderId());
            }
        });
        return responses.stream().filter(r->{
            if (ObjectUtil.isEmpty(request.getRecipient())){
                if (ObjectUtil.isEmpty(r.getRefundStatus())){
                    return true;
                }else {
                    String orderId = map.get(r.getId().toString());
                    return r.getOrderId().equals(orderId);
                }
            }else {
                if (ObjectUtil.isEmpty(r.getPhone())||ObjectUtil.isEmpty(r.getRecipient())){
                    return false;
                }
            }
            return r.getPhone().contains(request.getRecipient())||r.getRecipient().contains(request.getRecipient());
        }).collect(Collectors.toList());
    }

    /**
     * @description 生成礼品卡查询分页
     * @param request
     * @author Li
     * @date 2023/8/29 15:14
     * @return {@link PageInfo}<{@link CardProductResponse}>
     */
    @Override
    public PageInfo<CardProductResponse> cardProductPage(CardPageRequest request) {
        List<VcaProduct> products = productService.list(Wrappers.<VcaProduct>
                        lambdaQuery().eq(VcaProduct::getCid,750)
                        .eq(VcaProduct::getIsDeleted,0)
                .eq(ObjectUtil.isNotEmpty(request.getCardNo()),VcaProduct::getCardNo, request.getCardNo())
                .eq(ObjectUtil.isNotEmpty(request.getType()),VcaProduct::getUseAround, request.getType())
                .like(ObjectUtil.isNotEmpty(request.getKeywords()),VcaProduct::getName, request.getKeywords()));
        List<CardProductResponse> responses = VcaUtil.copyList(products, CardProductResponse.class);
        return PageUtils.startPage(responses, request.getPage(), request.getLimit());
    }

    /**
     * @description 生成礼品卡
     * @param id 生成礼品卡id
     * @param number 生成数量
     * @author Li
     * @date 2023/8/29 15:15
     * @return {@link boolean}
     */
    @Override
    public boolean generateCards(Integer id,Integer number) {
        VcaProduct product = productService.getOne(Wrappers.<VcaProduct>lambdaQuery().eq(VcaProduct::getId, id));
        if (product.getStock()<number){
            throw new VcaException("生成礼品卡数量不可大于库存");
        }
        List<UserCard> userCards=new ArrayList<>();
        for (int i = 0; i < number; i++) {
            userCards.add(getCard(product,0,null));
        }
        int stock=product.getStock()-number;
        boolean update = productService.update(
                Wrappers.<VcaProduct>lambdaUpdate()
                        .eq(VcaProduct::getId, id)
                        .set(VcaProduct::getStock, stock));
        if (update){
            return this.saveBatch(userCards);
        }
        return false;
    }

    @Override
    public boolean taggedCards(List<Integer> ids) {

        //查询是否已被标记赠送
        List<VcaUserCardRecord> list = userCardRecordService.list(
                Wrappers.<VcaUserCardRecord>lambdaQuery()
                        .in(VcaUserCardRecord::getCardId, ids)
                        .eq(VcaUserCardRecord::getSendUser, 0));
        //取出已被赠送的礼品卡id并从选择被标记中删除
        List<Integer> collect = list.stream().map(VcaUserCardRecord::getCardId).collect(Collectors.toList());
        ids.removeAll(collect);
        //查询礼品卡并添加赠送记录
        if (ObjectUtil.isEmpty(ids)){
            return true;
        }
        List<UserCard> cards = this.list(Wrappers.<UserCard>lambdaQuery().in(UserCard::getId, ids));
        List<VcaUserCardRecord> records=new ArrayList<>();
        if (ObjectUtil.isEmpty(cards)){
            return true;
        }
        cards.forEach(c->{
            c.setGiftTime(new Date());
            VcaUserCardRecord record = new VcaUserCardRecord();
            record.setSendUser(0);
            record.setGetUser(0);
            record.setCardId(c.getId());
            record.setCreateTime(new Date());
            record.setDescription("后台赠送礼品卡");
            records.add(record);
        });
        if (this.saveOrUpdateBatch(cards)) {
            return userCardRecordService.saveBatch(records);
        }
        return false;
    }

    @Override
    public boolean remarkCards(RemarkCardsRequest request) {
        return this.update(
                Wrappers.<UserCard>lambdaUpdate()
                        .in(UserCard::getId, request.getIds())
                        .set(UserCard::getRemark,request.getRemark()));
    }

    public UserCard getCard(VcaProduct product,Integer uid,StoreOrderInfo orderInfo) {
        UserCard userCard = new UserCard();
        userCard.setUid(uid);
        if (ObjectUtil.isNotEmpty(orderInfo)){
            userCard.setCardId(orderInfo.getProductId());
            userCard.setOrderId(orderInfo.getMerOrderNo());
            userCard.setStutus(0);
            userCard.setName(orderInfo.getName());
            userCard.setNameEn(orderInfo.getNameEn());
            product = productService.getById(orderInfo.getProductId());
        }else if (ObjectUtil.isNotEmpty(product)){
            userCard.setCardId(product.getId());
            userCard.setStutus(0);
            userCard.setOrderId("");
            userCard.setName(product.getName());
            userCard.setNameEn(product.getNameEn());
        }else {
            log.error("生成礼品卡异常");
            throw new VcaException("生成礼品卡异常");
        }
        userCard.setCardNo(product.getCardNo()+RandomUtil.randomString(6) + System.currentTimeMillis());
        userCard.setMainColor(product.getMainColor());
        userCard.setSecondaryColor(product.getSecondaryColor());
        userCard.setTertiaryColor(product.getTertiaryColor());
        userCard.setIntroduction(product.getIntroduction());
        userCard.setIntroductionEn(product.getIntroductionEn());
        userCard.setFaceValue(product.getFaceValue());
        userCard.setStartTime(new Date());
        DateTime dateTime = cn.hutool.core.date.DateUtil.offset(new Date(), DateField.DAY_OF_YEAR, product.getEndTime() + 1);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(dateTime);
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        Date dayStart = calendar.getTime();
        userCard.setEndTime(dayStart);
        userCard.setIsDeleted(0);
        userCard.setType("online_buy");
        userCard.setUseType(product.getUseType());
        userCard.setPrimaryKey(product.getPrimaryKey());
        userCard.setUserAround(product.getUseAround());
        userCard.setUpdateTime(new Date());
        userCard.setCardType(2);
        userCard.setCdKey(product.getCardNo()+RandomUtil.randomString(8) + System.currentTimeMillis());
        return userCard;
    }

    /**
     * @Description:生成礼品卡过期小程序订阅消息
     * @author:chenbing
     * @date 2022/12/30 14:17
     */
    private void generateGiftCardBeOverdueRoutine(UserCard giftCard, Integer routineId) {
        //卡种{{thing1.DATA}}会员卡号{{character_string2.DATA}}备注{{thing3.DATA}}会员卡名称{{thing4.DATA}}
        HashMap<String, String> messageMap = new HashMap<>();
        messageMap.put("thing1", getCardType(giftCard));
        messageMap.put("character_string2", giftCard.getCardNo());
//        messageMap.put("thing3", "您的卡还有" + systemConfigService.getValueByKey(Constants.GIFT_CARD_DISABLE_TIME) + "日即将到期，请尽快使用！");
        messageMap.put("thing3", "您的礼品卡将于今日到期，请尽快使用");
        messageMap.put("thing4", giftCard.getName());
        UserToken userToken = userTokenService.getTokenByUserIdException(giftCard.getUid(), OrderRedisConstans.SYSTEM_TYPE_ROUTINE);
        if (userToken!=null) {
            templateMessageService.pushMiniTemplateMessage(routineId, messageMap, userToken.getToken(), "pages/user-gift-certificates-detail/index?id=" + giftCard.getId());
        }
    }

    /**
     * @Description:获取礼品卡类型
     * @author:chenbing
     * @date 2022/12/30 14:33
     */
    private String getCardType(UserCard giftCard) {
        String type = null;
        switch (giftCard.getUserAround()) {
            case 0:
                // TODO: 2022/12/30 课程
                type = getType(giftCard, "课程");
                break;
            case 1:
                // TODO: 2022/12/30 讲座
                type = getType(giftCard, "讲座");
                break;
            case 2:
                // TODO: 2022/12/30 展览
                type = getType(giftCard, "展览");
                break;
            default:
                break;
        }
        return type;
    }

    private String getType(UserCard giftCard, String typeName1) {
        String type = null;
        switch (giftCard.getUseType()) {
            case 1:
                // TODO: 2022/12/30 分类卡
                type = typeName1 + "分类卡";
                break;
            case 2:
                // TODO: 2022/12/30 课程卡/讲座卡/展览卡
                type = typeName1 + "卡";
                break;
            case 3:
                // TODO: 2022/12/30 通用卡
                type = typeName1 + "通用卡";
                break;
            default:
                break;
        }
        return type;
    }
}
